package com.yike.user.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yike.common.constant.CommonConstant;
import com.yike.common.exception.BusinessException;
import com.yike.common.redis.RedisUtil;
import com.yike.common.tool.*;
import com.yike.common.vo.LoginUserInfoVo;
import com.yike.order.api.param.ShopDataStatisticsFeignParam;
import com.yike.order.api.service.OrderFeignService;
import com.yike.order.api.vo.ShopDataStatisticsFeignVo;
import com.yike.websocket.api.param.MessageReminderFeignParam;
import com.yike.websocket.api.service.WebSocketFeignService;
import com.yike.user.entity.*;
import com.yike.user.mapper.*;
import com.yike.user.param.*;
import com.yike.user.service.ShopService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yike.common.base.BaseServiceImpl;
import com.yike.common.pagination.Paging;
import com.yike.common.pagination.PageInfo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yike.user.vo.*;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 店铺表 服务实现类
 *
 * @author Sakura
 * @since 2024-08-23
 */
@Slf4j
@Service
public class ShopServiceImpl extends BaseServiceImpl<ShopMapper, Shop> implements ShopService {

    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private ShopUserMapper shopUserMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private AgentMapper agentMapper;
    @Autowired
    private AgentShopMapper agentShopMapper;
    @Autowired
    private ShopBindingApplyMapper shopBindingApplyMapper;
    @Autowired
    private MerchantMapper merchantMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OpenDoorRecordMapper openDoorRecordMapper;
    @Autowired
    private ShopGarrisonRecordMapper shopGarrisonRecordMapper;
    @Resource
    private OrderFeignService orderFeignService;
    @Autowired
    private AgentShopCountMapper agentShopCountMapper;
    @Autowired
    private ShopCameraMapper shopCameraMapper;
    @Resource
    private WebSocketFeignService webSocketFeignService;

    @Autowired
    private MessageReminderMapper messageReminderMapper;

    @Autowired
    private ShopAdjustPriceMapper shopAdjustPriceMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveShop(ShopParam shopParam) throws Exception {
        // 创建店铺
        Shop shop = new Shop();
        BeanUtils.copyProperties(shopParam, shop);
        shop.setMerchantId(LoginUtil.getMerchantId());
        // 生产一个店铺编号
        shop.setShopNo("88" + StringUtil.getStrNo());
        shop.setCreateBy(LoginUtil.getUserId());
        shopMapper.insert(shop);

        // 创建店主
        ShopUser shopUser = new ShopUser();
        shopUser.setShopId(shop.getId());
        shopUser.setUserId(LoginUtil.getUserId());
        shopUser.setType(1);
        shopUser.setCreateBy(LoginUtil.getUserId());
        shopUserMapper.insert(shopUser);

        // 处理代理商绑定逻辑
        if (StringUtil.isNotBlank(shopParam.getAgentNo())) {
            // 如果代理商信息不为空则直接绑定店铺到代理商
            AgentShop agentShop = new AgentShop();
            agentShop.setShopId(shop.getId());
            // 如果是手机号则需要通过手机号获取代理商信息
            if (StringUtil.isValidPhoneNumber(shopParam.getAgentNo())) {
                // 先根据手机号获取用户信息
                User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                        .eq(User::getMobile, shopParam.getAgentNo()));
                if (user == null) {
                    throw new BusinessException("代理商不存在，请检查手机号是否正确");
                }
                // 再获取代理商信息
                Agent agent = agentMapper.selectOne(Wrappers.lambdaQuery(Agent.class)
                        .eq(Agent::getUserId, user.getId()));
                if (agent == null) {
                    throw new BusinessException("代理商不存在，请检查手机号是否正确");
                }
                agentShop.setAgentId(agent.getId());
            } else {
                // 获取代理商信息
                Agent agent = agentMapper.selectOne(Wrappers.lambdaQuery(Agent.class)
                        .eq(Agent::getAgentNo, shopParam.getAgentNo()));
                if (agent == null) {
                    throw new BusinessException("代理商信息异常");
                }
                agentShop.setAgentId(agent.getId());
            }
            agentShopMapper.insert(agentShop);
        }

        return true;
    }

    @Override
    @Transactional
    public boolean createAgentShop(AgentCreateShopParam agentCreateShopParam) throws Exception {
        // 创建店铺
        Shop shop = new Shop();
        BeanUtils.copyProperties(agentCreateShopParam, shop);
        // 生产一个店铺编号
        shop.setShopNo("88" + StringUtil.getStrNo());
        shop.setCreateBy(LoginUtil.getUserId());
        shopMapper.insert(shop);

        // 将店铺和代理商关联起来
        AgentShop agentShop = new AgentShop();
        agentShop.setShopId(shop.getId());
        agentShop.setAgentId(LoginUtil.getAgentId());
        agentShopMapper.insert(agentShop);

        // 添加逻辑，代理商创建店铺的时候就需要发送一个绑定申请的消息
        if (StringUtil.isNotBlank(agentCreateShopParam.getMobile())) {
            // 先根据手机号获取用户信息
            User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                    .eq(User::getMobile, agentCreateShopParam.getMobile()));
            // 如果联系人还未注册直接返回
            if (user == null) {
                // 如果用户不存在则创建一个用户
                user = new User();
                BeanUtils.copyProperties(agentCreateShopParam, user);
                user.setUserNo(StringUtil.random(32)); // 生成用户ID
                user.setNickname(agentCreateShopParam.getContact());
                user.setSource(agentCreateShopParam.getShopName());
                user.setCreateBy(LoginUtil.getUserId());
                userMapper.insert(user);
            }
            // 再获取商户信息
            Merchant merchant = merchantMapper.selectOne(Wrappers.lambdaQuery(Merchant.class)
                    .eq(Merchant::getUserId, user.getId()));
            // 如果联系人还未成为商家直接返回
            if (merchant == null) {
                // 创建一条商户记录
                merchant = new Merchant();
                BeanUtils.copyProperties(agentCreateShopParam, merchant);
                merchant.setMerchantNo("86" + StringUtil.getStrNo());
                merchant.setUserId(user.getId());
                merchant.setName(agentCreateShopParam.getShopName());
                merchant.setCreateBy(LoginUtil.getUserId());
                merchantMapper.insert(merchant);
            }

            // 生成一条申请信息
            ShopBindingApply shopBindingApply = new ShopBindingApply();
            shopBindingApply.setShopId(shop.getId());
            shopBindingApply.setStatus(0);
            shopBindingApply.setType(2);
            shopBindingApply.setCreateBy(LoginUtil.getUserId());
            shopBindingApply.setMerchantId(merchant.getId());
            shopBindingApply.setAgentId(LoginUtil.getAgentId());
            shopBindingApplyMapper.insert(shopBindingApply);

            // 保存一条推送消息
            MessageReminder messageReminder = new MessageReminder();
            messageReminder.setMsgType(1);
            messageReminder.setUserId(user.getId());
            messageReminder.setCorrelationId(shopBindingApply.getId());
            messageReminder.setMsgStatus(0);
            messageReminder.setCheckStatus(0);
            messageReminder.setDescription("收到ID " + LoginUtil.getAgentNo() + " 代理商的关联申请，请确认");
            messageReminder.setCreateBy(LoginUtil.getUserId());
            messageReminderMapper.insert(messageReminder);

            // 通过websocket推送消息
            MessageReminderFeignParam messageReminderFeignParam = new MessageReminderFeignParam();
            BeanUtils.copyProperties(messageReminder, messageReminderFeignParam);
            messageReminderFeignParam.setAgentName(LoginUtil.getAgentName());
            messageReminderFeignParam.setAgentNo(LoginUtil.getAgentNo());
            webSocketFeignService.senMessageReminder(messageReminderFeignParam);
        }

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateShop(ShopParam shopParam) throws Exception {
        // 先获取店铺信息
        Shop shop = shopMapper.selectOne(Wrappers.lambdaQuery(Shop.class)
                .eq(Shop::getShopNo, shopParam.getShopNo()));
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }
        // 获取店主信息，只有店主或创建人可以修改
        ShopUser shopUser = shopUserMapper.selectOne(Wrappers.lambdaQuery(ShopUser.class)
                .eq(ShopUser::getShopId, shop.getId())
                .eq(ShopUser::getUserId, LoginUtil.getUserId())
                .eq(ShopUser::getType, 1));
        if (shopUser == null && !shop.getCreateBy().equals(LoginUtil.getUserId())) {
            throw new BusinessException("店铺信息异常");
        }
        BeanUtils.copyProperties(shopParam, shop);
        shop.setUpdateBy(LoginUtil.getUserId());

        // 处理代理商绑定逻辑
        if (StringUtil.isNotBlank(shopParam.getAgentNo())) {
            // 先判断当前商户有没有绑定代理商
            AgentShop agentShop = agentShopMapper.selectOne(Wrappers.lambdaQuery(AgentShop.class)
                    .eq(AgentShop::getShopId, shop.getId()));
            if (agentShop != null) {
                throw new BusinessException("该店铺已绑定代理商");
            }
            // 如果代理商信息不为空则直接绑定店铺到代理商
            agentShop = new AgentShop();
            agentShop.setShopId(shop.getId());
            // 如果是手机号则需要通过手机号获取代理商信息
            if (StringUtil.isValidPhoneNumber(shopParam.getAgentNo())) {
                // 先根据手机号获取用户信息
                User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                        .eq(User::getMobile, shopParam.getAgentNo()));
                if (user == null) {
                    throw new BusinessException("代理商不存在，请检查手机号是否正确");
                }
                // 再获取代理商信息
                Agent agent = agentMapper.selectOne(Wrappers.lambdaQuery(Agent.class)
                        .eq(Agent::getUserId, user.getId()));
                if (agent == null) {
                    throw new BusinessException("代理商不存在，请检查手机号是否正确");
                }
                agentShop.setAgentId(agent.getId());
            } else {
                // 获取代理商信息
                Agent agent = agentMapper.selectOne(Wrappers.lambdaQuery(Agent.class)
                        .eq(Agent::getAgentNo, shopParam.getAgentNo()));
                if (agent == null) {
                    throw new BusinessException("代理商信息异常");
                }
                agentShop.setAgentId(agent.getId());
            }
            agentShopMapper.insert(agentShop);
        }

        return super.updateById(shop);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteShop(String shopNo) throws Exception {
        // 先获取店铺信息
        Shop shop = shopMapper.selectOne(Wrappers.lambdaQuery(Shop.class)
                .eq(Shop::getShopNo, shopNo));
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }
        // 获取店主信息，只有店主或创建人可以修改
        ShopUser shopUser = shopUserMapper.selectOne(Wrappers.lambdaQuery(ShopUser.class)
                .eq(ShopUser::getShopId, shop.getId())
                .eq(ShopUser::getUserId, LoginUtil.getUserId())
                .eq(ShopUser::getType, 1));
        if (shopUser == null && !shop.getCreateBy().equals(LoginUtil.getUserId())) {
            throw new BusinessException("店铺信息异常");
        }

        return super.removeById(shop.getId());
    }

    @Override
    public ShopVo getShop(String shopNo) throws Exception {
        // 根据code获取店铺信息
        ShopVo shopVo = shopMapper.getShopInfo(shopNo);
        if (shopVo == null) {
            throw new BusinessException("店铺信息异常");
        }
        // 根据登录人判断是否可以审批
        // 如果登录用户是代理商则可以审核type为1的 如果登录用户为商家则可以审核type为2的
        if (shopVo.getApplyStatus() != null && shopVo.getApplyStatus() == 0) {
            if ((shopVo.getApplyType() == 1 && LoginUtil.getUserType() == 3) || (shopVo.getApplyType() == 2 && LoginUtil.getUserType() == 2)) {
                shopVo.setCheckFlag(1);
            } else {
                shopVo.setCheckFlag(0);
            }
        }
        // 获取日期
        LocalDate date = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 将日期格式化为字符串
        String strDate = date.format(formatter);
        // 获取店铺交易数据
        AgentShopCommissionVo agentShopCommissionVo = agentShopCountMapper.getAgentShopCommission(shopVo.getAgentId(),
                shopVo.getId(), strDate, null, null);
        if (agentShopCommissionVo != null) {
            BeanUtils.copyProperties(agentShopCommissionVo, shopVo);
        }
        return shopVo;
    }

    @Override
    public Paging<ShopVo> getUserShopList(ShopPageParam shopPageParam) throws Exception {
        Page<Shop> page = new PageInfo<>(shopPageParam);
        IPage<ShopVo> iPage = shopMapper.getUserShopList(page, LoginUtil.getUserId(), shopPageParam);
        for (ShopVo shopVo : iPage.getRecords()) {
            // 根据登录人判断是否可以审批
            // 如果登录用户是代理商则可以审核type为1的 如果登录用户为商家则可以审核type为2的
            if (shopVo.getApplyStatus() != null && shopVo.getApplyStatus() == 0) {
                if ((shopVo.getApplyType() == 1 && LoginUtil.getUserType() == 3) || (shopVo.getApplyType() == 2 && LoginUtil.getUserType() == 2)) {
                    shopVo.setCheckFlag(1);
                } else {
                    shopVo.setCheckFlag(0);
                }
            }
        }
        return new Paging<ShopVo>(iPage);
    }

    @Override
    public Paging<ShopVo> getAgentShopList(ShopPageParam shopPageParam) throws Exception {
        Page<Shop> page = new PageInfo<>(shopPageParam);
        IPage<ShopVo> iPage = shopMapper.getAgentShopList(page, LoginUtil.getUserId(), shopPageParam);
        // 获取日期
        LocalDate date = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 将日期格式化为字符串
        String strDate = date.format(formatter);
        for (ShopVo shopVo : iPage.getRecords()) {
            // 获取店铺交易数据
            AgentShopCommissionVo agentShopCommissionVo = agentShopCountMapper.getAgentShopCommission(shopVo.getAgentId(),
                    shopVo.getId(), strDate, null, null);
            if (agentShopCommissionVo != null) {
                BeanUtils.copyProperties(agentShopCommissionVo, shopVo);
            }
            // 获取店铺摄像头数据
            List<String> cameras = shopCameraMapper.getShopCameraList(shopVo.getId());
            shopVo.setCameras(cameras);
        }
        return new Paging<ShopVo>(iPage);
    }

    @Override
    public Paging<ShopVo> getAgentCreateShopList(ShopPageParam shopPageParam) throws Exception {
        Page<Shop> page = new PageInfo<>(shopPageParam);
        IPage<ShopVo> iPage = shopMapper.getAgentCreateShopList(page, LoginUtil.getUserId(), shopPageParam);
        for (ShopVo shopVo : iPage.getRecords()) {
            // 根据登录人判断是否可以审批
            // 如果登录用户是代理商则可以审核type为1的 如果登录用户为商家则可以审核type为2的
            if (shopVo.getApplyStatus() != null && shopVo.getApplyStatus() == 0) {
                if ((shopVo.getApplyType() == 1 && LoginUtil.getUserType() == 3) || (shopVo.getApplyType() == 2 && LoginUtil.getUserType() == 2)) {
                    shopVo.setCheckFlag(1);
                } else {
                    shopVo.setCheckFlag(0);
                }
            }
        }
        return new Paging<ShopVo>(iPage);
    }

    @Override
    public Paging<ShopVo> getSubAgentShopList(SubAgentShopPageParam subAgentShopPageParam) throws Exception {
        Page<Shop> page = new PageInfo<>(subAgentShopPageParam);
        IPage<ShopVo> iPage = shopMapper.getSubAgentShopList(page, LoginUtil.getUserId(), subAgentShopPageParam);
        // 获取日期
        LocalDate date = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 将日期格式化为字符串
        String strDate = date.format(formatter);
        for (ShopVo shopVo : iPage.getRecords()) {
            // 获取店铺交易数据
            AgentShopCommissionVo agentShopCommissionVo = agentShopCountMapper.getAgentShopCommission(shopVo.getAgentId(),
                    shopVo.getId(), strDate, null, null);
            if (agentShopCommissionVo != null) {
                BeanUtils.copyProperties(agentShopCommissionVo, shopVo);
            }
        }
        return new Paging<ShopVo>(iPage);
    }

    @Override
    public ShopVo scanCode(ScanShopCodeParam scanShopCodeParam) {
        // 根据code获取店铺信息
        Shop shop = shopMapper.selectOne(new LambdaQueryWrapper<Shop>().eq(Shop::getShopNo, scanShopCodeParam.getCode()));
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }

        // 扫码的时候顺便开门，目前无开门程序入口，待完善
        // 根据经度维度判断距离，距离小于500m才开门（注意这个距离可以根据定位工具的精确度进行调整，目前不知道定位精确度）
        if (shop.getLongitude() != null && shop.getLatitude() != null && scanShopCodeParam.getLongitude() != null
                && scanShopCodeParam.getLatitude() != null) {
            // 使用Haversine公式计算两个坐标的球面距离
            double distance = HaversineCalculator.calculateDistance(shop.getLatitude().doubleValue(),
                    shop.getLongitude().doubleValue(), scanShopCodeParam.getLatitude().doubleValue(),
                    scanShopCodeParam.getLongitude().doubleValue());
            log.info("当前开门距离为：" + distance);
            // 在这里面调用开门程序即可
            if (distance < 500) {
                log.info("执行开门程序+++++++++++++++++++++");

                // 添加一条开门记录用来统计人数
                OpenDoorRecord openDoorRecord = new OpenDoorRecord();
                openDoorRecord.setShopId(shop.getId());
                openDoorRecord.setUserId(LoginUtil.getUserId());
                openDoorRecord.setCreateTime(new Date());
                openDoorRecordMapper.insert(openDoorRecord);
            }
        }

        // 缓存用户选择的店铺，和用户当前token绑定
        redisUtil.set(CommonConstant.USER_SHOP_NO_TOKEN + TokenUtil.getToken(), shop.getShopNo(), 24 * 60 * 60);

        // 获取用户信息，如果用户是第一次扫码则绑定店铺信息到用户
        User user = userMapper.selectById(LoginUtil.getUserId());
        if (StringUtil.isBlank(user.getSource())) {
            user.setSource(shop.getShopName());
            user.setProvCode(shop.getProvCode());
            user.setCityCode(shop.getCityCode());
            user.setDistCode(shop.getDistCode());
            userMapper.updateById(user);
        }

        ShopVo shopVo = new ShopVo();
        BeanUtils.copyProperties(shop, shopVo);
        return shopVo;
    }

    @Override
    public ShopVo chooseShop(String shopNo) {

        // 获取店铺信息
        Shop shop = shopMapper.selectOne(Wrappers.lambdaQuery(Shop.class)
                .eq(Shop::getShopNo, shopNo));
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }
        // 获取店铺用户信息
        ShopUser shopUser = shopUserMapper.selectOne(Wrappers.lambdaQuery(ShopUser.class)
                .eq(ShopUser::getUserId, LoginUtil.getUserId())
                .eq(ShopUser::getShopId, shop.getId()));
        if (shopUser == null) {
            throw new BusinessException("店铺信息异常");
        }
        // 缓存用户选择的店铺，和用户当前token绑定
        LoginUserInfoVo loginUserInfoVo = LoginUtil.getLoginUserInfoVo();
        loginUserInfoVo.setShopNo(shopNo);
        loginUserInfoVo.setShopId(shop.getId());
        redisUtil.set(TokenUtil.getToken(), loginUserInfoVo, 30 * 24 * 60 * 60);

        ShopVo shopVo = new ShopVo();
        BeanUtils.copyProperties(shop, shopVo);
        return shopVo;
    }

    @Override
    public List<ShopVo> getAroundShopList(AroundShopParam aroundShopParam) {
        List<ShopVo> shopVos = shopMapper.getAroundShopList(aroundShopParam);
        if (shopVos.isEmpty()) {
            // 测试用，防止出现周围没有店铺的情况
            aroundShopParam.setDistance(5000000);
            shopVos = shopMapper.getAroundShopList(aroundShopParam);
        }
//        // 测试用
//        for (ShopVo shopVo:shopVos) {
//            // 计算距离
//            // 使用Haversine公式计算两个坐标的球面距离
//            double distance = HaversineCalculator.calculateDistance(shopVo.getLatitude().doubleValue(),
//                    shopVo.getLongitude().doubleValue(), aroundShopParam.getLatitude().doubleValue(),
//                    aroundShopParam.getLongitude().doubleValue());
//            log.info("当前开门距离为111111111111：" + distance);
//            log.info("当前开门距离为222222222222：" + shopVo.getDistance());
//        }

        return shopVos;
    }

    @Override
    public boolean getCloudGarrisonFlag() {
        // 获取店铺信息
        Shop shop = shopMapper.selectById(LoginUtil.getShopId());
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }
        return shop.getCloudGarrisonFlag() != null && shop.getCloudGarrisonFlag();
    }

    @Override
    public boolean setCloudGarrisonFlag(SetCloudGarrisonFlagParam setCloudGarrisonFlagParam) {
        if (StringUtil.isBlank(setCloudGarrisonFlagParam.getShopNo())) {
            setCloudGarrisonFlagParam.setShopNo(LoginUtil.getShopNo());
        }
        // 获取店铺信息
        Shop shop = shopMapper.selectOne(Wrappers.lambdaQuery(Shop.class)
                .eq(Shop::getShopNo, setCloudGarrisonFlagParam.getShopNo()));
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }
        // 判断是否是开启
        Date truncatedDate = DateUtils.truncate(new Date(), Calendar.SECOND);
        if (setCloudGarrisonFlagParam.getCloudGarrisonFlag()) {
            shop.setCloudGarrisonCode(StringUtil.getStrNo());

            // 生成一条开启记录
            ShopGarrisonRecord shopGarrisonRecord = new ShopGarrisonRecord();
            shopGarrisonRecord.setShopId(shop.getId());
            shopGarrisonRecord.setBeginTime(truncatedDate);
            shopGarrisonRecord.setCloudGarrisonCode(shop.getCloudGarrisonCode());
            shopGarrisonRecord.setCreateTime(truncatedDate);
            shopGarrisonRecord.setCreateBy(LoginUtil.getUserId());
            shopGarrisonRecordMapper.insert(shopGarrisonRecord);

            // 此处还需要调用开启云驻守程序

        }

        // 关闭的时候获取上一条未关闭的记录
        ShopGarrisonRecord shopGarrisonRecord = shopGarrisonRecordMapper.selectOne(Wrappers.lambdaQuery(ShopGarrisonRecord.class)
                .eq(ShopGarrisonRecord::getShopId, shop.getId())
                .isNull(ShopGarrisonRecord::getEndTime)
                .ne(ShopGarrisonRecord::getBeginTime, truncatedDate)
                .orderByDesc(ShopGarrisonRecord::getCreateTime)
                .last("limit 1"));
        if (shopGarrisonRecord != null) {
            shopGarrisonRecord.setEndTime(truncatedDate);
            shopGarrisonRecord.setUpdateBy(LoginUtil.getUserId());
            shopGarrisonRecord.setUpdateTime(truncatedDate);
            shopGarrisonRecordMapper.updateById(shopGarrisonRecord);
        }

        shop.setCloudGarrisonFlag(setCloudGarrisonFlagParam.getCloudGarrisonFlag());
        shopMapper.updateById(shop);

        return true;
    }

    @Override
    @Transactional
    public boolean shopBinding(ShopBindingParam shopBindingParam) throws Exception {
        Shop shop;
        // 添加判断，如果店铺编号是手机号，则需要先根据手机号获取到店铺信息
        if (StringUtil.isValidPhoneNumber(shopBindingParam.getShopNo())) {
            // 获取当前手机号所在商家未绑定店铺信息，如果存在多个只获取一个即可
            shop = shopMapper.getMerchantNotBindShop(shopBindingParam.getShopNo());
        } else {
            // 获取店铺信息
            shop = shopMapper.selectOne(Wrappers.lambdaQuery(Shop.class)
                    .eq(Shop::getShopNo, shopBindingParam.getShopNo()));
        }
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }

        // 先根据手机号获取用户信息
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getMobile, shop.getMobile()));
        if (user == null) {
            throw new BusinessException("商家不存在，请检查手机号是否正确");
        }
        // 再获取商户信息
        Merchant merchant = merchantMapper.selectOne(Wrappers.lambdaQuery(Merchant.class)
                .eq(Merchant::getUserId, user.getId()));
        if (merchant == null) {
            throw new BusinessException("商家不存在，请检查手机号是否正确");
        }

        // 调整逻辑，用户可以重复发起申请，只需要间隔两分钟即可
        if (redisUtil.hasKey(CommonConstant.SHOP_BINDING_APPLY + shop.getId())) {
            throw new BusinessException(500, "请勿重复操作，2分钟后再试");
        }
        redisUtil.set(CommonConstant.SHOP_BINDING_APPLY + shop.getId(), 1, 2 * 60);

        // 生成一条申请信息
        ShopBindingApply shopBindingApply = new ShopBindingApply();
        shopBindingApply.setShopId(shop.getId());
        shopBindingApply.setMerchantId(merchant.getId());
        shopBindingApply.setStatus(0);
        shopBindingApply.setType(shopBindingParam.getType());
        shopBindingApply.setCreateBy(LoginUtil.getUserId());
        shopBindingApply.setAgentId(LoginUtil.getAgentId());
        shopBindingApplyMapper.insert(shopBindingApply);

        // 保存一条推送消息
        MessageReminder messageReminder = new MessageReminder();
        messageReminder.setMsgType(1);
        messageReminder.setUserId(user.getId());
        messageReminder.setCorrelationId(shopBindingApply.getId());
        messageReminder.setMsgStatus(0);
        messageReminder.setCheckStatus(0);
        messageReminder.setDescription("收到ID " + LoginUtil.getAgentNo() + " 代理商的关联申请（店铺：" + shop.getShopName() + "）" + ", 请确认!");
        messageReminder.setCreateBy(LoginUtil.getUserId());
        messageReminderMapper.insert(messageReminder);

        // 通过websocket推送消息
        MessageReminderFeignParam messageReminderFeignParam = new MessageReminderFeignParam();
        BeanUtils.copyProperties(messageReminder, messageReminderFeignParam);
        if (shopBindingParam.getType() == 2) {
            messageReminderFeignParam.setAgentName(LoginUtil.getAgentName());
            messageReminderFeignParam.setAgentNo(LoginUtil.getAgentNo());
        }
        webSocketFeignService.senMessageReminder(messageReminderFeignParam);

        return true;
    }

    @Override
    public Paging<ShopBindingVo> getShopBindingList(ShopBindingPageParam shopBindingPageParam) throws Exception {
        // 根据登录用户类型判断当前用户是哪一端登录
        Long merchantId = null;
        if (LoginUtil.getUserType() == 2) {
            merchantId = LoginUtil.getMerchantId();
        }
        Long agentId = null;
        if (LoginUtil.getUserType() == 3) {
            agentId = LoginUtil.getAgentId();
        }
        Page<ShopBindingApply> page = new PageInfo<>(shopBindingPageParam);
        IPage<ShopBindingVo> iPage = shopBindingApplyMapper.getShopBindingApplyList(page, agentId, merchantId, shopBindingPageParam);
        // 根据登录人判断是否可以审批
        for (ShopBindingVo shopBindingVo : iPage.getRecords()) {
            // 如果登录用户是代理商则可以审核type为1的 如果登录用户为商家则可以审核type为2的
            if ((shopBindingVo.getApplyType() == 1 && LoginUtil.getUserType() == 3) || (shopBindingVo.getApplyType() == 2 && LoginUtil.getUserType() == 2)) {
                shopBindingVo.setCheckFlag(1);
            } else {
                shopBindingVo.setCheckFlag(0);
            }
        }
        return new Paging<ShopBindingVo>(iPage);
    }

    @Override
    public ShopBindingVo getShopBinding(Long applyId) throws Exception {
        ShopBindingVo shopBindingVo = shopBindingApplyMapper.getShopBindingApply(applyId);
        if (shopBindingVo == null) {
            throw new BusinessException("申请信息异常");
        }
        // 根据登录人判断是否可以审批
        // 如果登录用户是代理商则可以审核type为1的 如果登录用户为商家则可以审核type为2的
        if ((shopBindingVo.getApplyType() == 1 && LoginUtil.getUserType() == 3) || (shopBindingVo.getApplyType() == 2 && LoginUtil.getUserType() == 2)) {
            shopBindingVo.setCheckFlag(1);
        } else {
            shopBindingVo.setCheckFlag(0);
        }

        return shopBindingVo;
    }

    @Override
    public boolean checkShopBinding(CheckShopBindingParam checkShopBindingParam) throws Exception {
        // 获取绑定申请信息
        ShopBindingApply shopBindingApply = shopBindingApplyMapper.selectById(checkShopBindingParam.getId());
        if (shopBindingApply == null || shopBindingApply.getStatus() != 0) {
            throw new BusinessException("申请信息异常");
        }

        // 判断店铺信息是否正常
        Shop shop = shopMapper.selectById(shopBindingApply.getShopId());
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }

        // 判断是否是通过
        if (checkShopBindingParam.getStatus() == 1) {
            // 区分是绑定代理商还是绑定商家
            if (shopBindingApply.getType() == 1) {
                // 1为店铺绑定代理商
                Agent agent = agentMapper.selectById(shopBindingApply.getAgentId());
                if (agent == null) {
                    throw new BusinessException("代理商信息异常");
                }
                // 如果当前店铺已经绑定了代理商则替换新的代理商
//                agentShopMapper.delete(Wrappers.lambdaQuery(AgentShop.class)
//                        .eq(AgentShop::getShopId, shopBindingApply.getShopId()));

                // 如果当前店铺已经绑定代理商则直接拒绝
                AgentShop agentShop = agentShopMapper.selectOne(Wrappers.lambdaQuery(AgentShop.class)
                        .eq(AgentShop::getShopId, shop.getId()));
                if (agentShop != null) {
                    throw new BusinessException("该店铺已经绑定代理商，如需更换代理商请联系平台");
                }

                // 将当前店铺和代理商关联起来
                agentShop = new AgentShop();
                agentShop.setShopId(shopBindingApply.getShopId());
                agentShop.setAgentId(shopBindingApply.getAgentId());
                agentShop.setCreateBy(LoginUtil.getUserId());
                agentShop.setCreateTime(new Date());
                agentShopMapper.insert(agentShop);
            } else {
                // 2为店铺绑定商家
                Merchant merchant = merchantMapper.selectById(shopBindingApply.getMerchantId());
                if (merchant == null) {
                    throw new BusinessException("商家信息异常");
                }
                // 如果当前店铺已经绑定了商家则替换新的商家
//                shopUserMapper.delete(Wrappers.lambdaQuery(ShopUser.class)
//                        .eq(ShopUser::getShopId, shopBindingApply.getShopId()));

                // 如果店铺已经绑定商家了则直接拒绝
                if (shop.getMerchantId() != null) {
                    throw new BusinessException("该店铺已经绑定商家，如需更换商家请联系平台");
                }

                // 将当前店铺和商家关联起来
                shop.setMerchantId(shopBindingApply.getMerchantId());
                shop.setUpdateBy(LoginUtil.getUserId());
                shop.setUpdateTime(new Date());
                shopMapper.updateById(shop);

                ShopUser shopUser = new ShopUser();
                shopUser.setShopId(shopBindingApply.getShopId());
                shopUser.setUserId(merchant.getUserId());
                shopUser.setType(1);
                shopUser.setCreateBy(LoginUtil.getUserId());
                shopUser.setCreateTime(new Date());
                shopUserMapper.insert(shopUser);
            }
        }
        if (shopBindingApply.getType() == 1) {
            shopBindingApplyMapper.update(
                    null,
                    Wrappers.lambdaUpdate(ShopBindingApply.class)
                            .set(ShopBindingApply::getStatus, checkShopBindingParam.getStatus())
                            .set(ShopBindingApply::getUpdateTime, new Date())
                            .set(ShopBindingApply::getUpdateBy, LoginUtil.getUserId())
                            .eq(ShopBindingApply::getAgentId, shopBindingApply.getAgentId())
                            .eq(ShopBindingApply::getShopId, shopBindingApply.getShopId())
            );

            shopBindingApplyMapper.delete(Wrappers.lambdaUpdate(ShopBindingApply.class)
                    .eq(ShopBindingApply::getAgentId, shopBindingApply.getAgentId())
                    .eq(ShopBindingApply::getShopId, shopBindingApply.getShopId()));
        } else {
            shopBindingApplyMapper.update(
                    null, // 第一个参数为null，因为我们在UpdateWrapper中指定了set内容
                    Wrappers.lambdaUpdate(ShopBindingApply.class)
                            .set(ShopBindingApply::getStatus, checkShopBindingParam.getStatus())
                            .set(ShopBindingApply::getUpdateTime, new Date())
                            .set(ShopBindingApply::getUpdateBy, LoginUtil.getUserId())
                            .eq(ShopBindingApply::getMerchantId, shopBindingApply.getMerchantId())
                            .eq(ShopBindingApply::getShopId, shopBindingApply.getShopId())
            );
        }

        // 获取消息推送信息
        MessageReminder messageReminder = messageReminderMapper.selectOne(Wrappers.lambdaQuery(MessageReminder.class)
                .eq(MessageReminder::getCorrelationId, shopBindingApply.getId())
                .eq(MessageReminder::getMsgType, 1));
        if (messageReminder != null) {
            messageReminder.setCheckStatus(checkShopBindingParam.getStatus());
            messageReminder.setMsgStatus(1);// 已读
            messageReminder.setUpdateBy(LoginUtil.getUserId());
            messageReminder.setUpdateTime(new Date());
            messageReminderMapper.updateById(messageReminder);
        }

        return true;
    }

    @Override
    public boolean adjustPrice(AdjustPriceParam adjustPriceParam) throws Exception {
        if (StringUtil.isBlank(adjustPriceParam.getShopNo())) {
            adjustPriceParam.setShopNo(LoginUtil.getShopNo());
        }
        // 获取店铺信息
        Shop shop = shopMapper.selectOne(Wrappers.lambdaQuery(Shop.class)
                .eq(Shop::getShopNo, adjustPriceParam.getShopNo()));
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }

        if (adjustPriceParam.getAdjustPriceFlag() != null) {
            shop.setAdjustPriceFlag(adjustPriceParam.getAdjustPriceFlag());
        }
        if (adjustPriceParam.getAdjustPriceRate() != null && adjustPriceParam.getAdjustPriceRate() != 0) {
            shop.setAdjustPriceRate(adjustPriceParam.getAdjustPriceRate());
        }

        // 添加一条调价记录
        ShopAdjustPrice shopAdjustPrice = new ShopAdjustPrice();
        shopAdjustPrice.setShopId(shop.getId());
        shopAdjustPrice.setAdjustPriceRate(adjustPriceParam.getAdjustPriceRate());
        shopAdjustPriceMapper.insert(shopAdjustPrice);

        shopMapper.updateById(shop);

        return true;
    }

    @Override
    public AdjustPriceVo getShopAdjustPrice() throws Exception {
        // 获取店铺信息
        Shop shop = shopMapper.selectById(LoginUtil.getShopId());
        if (shop == null) {
            throw new BusinessException("店铺信息异常");
        }

        AdjustPriceVo adjustPriceVo = new AdjustPriceVo();
        BeanUtils.copyProperties(shop, adjustPriceVo);
        return adjustPriceVo;
    }

    @Override
    public ShopDataStatisticsVo getShopDataStatistics(ShopDataStatisticsParam shopDataStatisticsParam) throws Exception {
        // 如果前端没有传shopId尝试从登录信息获取
        if (shopDataStatisticsParam.getShopId() == null) {
            shopDataStatisticsParam.setShopId(LoginUtil.getShopId());
        }
        // 添加逻辑，如果前端没有传日期参数则表示获取最后一次值守数据
        if (StringUtil.isBlank(shopDataStatisticsParam.getBeginTime()) && StringUtil.isBlank(shopDataStatisticsParam.getEndTime())
                && StringUtil.isBlank(shopDataStatisticsParam.getCertainDate())) {
            ShopGarrisonRecord shopGarrisonRecord = shopGarrisonRecordMapper
                    .selectOne(Wrappers.lambdaQuery(ShopGarrisonRecord.class)
                            .eq(ShopGarrisonRecord::getShopId, shopDataStatisticsParam.getShopId())
                            .orderByDesc(ShopGarrisonRecord::getCreateTime)
                            .last("LIMIT 1"));
            if (shopGarrisonRecord != null) {
                shopDataStatisticsParam.setBeginTime(DateUtil.format(shopGarrisonRecord.getBeginTime(), "yyyy-MM-dd HH:mm:ss"));
                if (shopGarrisonRecord.getEndTime() == null) {
                    shopGarrisonRecord.setEndTime(new Date());
                }
                shopDataStatisticsParam.setEndTime(DateUtil.format(shopGarrisonRecord.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
            }
        }
        if (StringUtil.isNotBlank(shopDataStatisticsParam.getBeginTime()) && shopDataStatisticsParam.getBeginTime().length() < 15) {
            shopDataStatisticsParam.setBeginTime(shopDataStatisticsParam.getBeginTime() + " 00:00:00");
        }
        if (StringUtil.isNotBlank(shopDataStatisticsParam.getEndTime()) && shopDataStatisticsParam.getEndTime().length() < 15) {
            shopDataStatisticsParam.setEndTime(shopDataStatisticsParam.getEndTime() + " 23:59:59");
        }
        // 获取进店人数
        Integer cmeShopNumber = openDoorRecordMapper.getComeShopNumber(shopDataStatisticsParam.getShopId(),
                shopDataStatisticsParam.getCertainDate(), shopDataStatisticsParam.getBeginTime(),
                shopDataStatisticsParam.getEndTime());
        // 去订单服务获取交易数据
        ShopDataStatisticsFeignParam shopDataStatisticsFeignParam = new ShopDataStatisticsFeignParam();
        BeanUtils.copyProperties(shopDataStatisticsParam, shopDataStatisticsFeignParam);
        ShopDataStatisticsFeignVo shopDataStatisticsFeignVo = orderFeignService.getShopDataStatistics(shopDataStatisticsFeignParam);
        ShopDataStatisticsVo shopDataStatisticsVo = new ShopDataStatisticsVo();
        BeanUtils.copyProperties(shopDataStatisticsFeignVo, shopDataStatisticsVo);
        shopDataStatisticsVo.setComeShopNumber(cmeShopNumber);
        return shopDataStatisticsVo;
    }

    @Override
    public Paging<ShopGarrisonDataVo> getShopGarrisonDataList(ShopGarrisonDataPageParam shopGarrisonDataPageParam) throws Exception {
        // 如果前端没有传shopId尝试从登录信息获取
        if (shopGarrisonDataPageParam.getShopId() == null) {
            shopGarrisonDataPageParam.setShopId(LoginUtil.getShopId());
        }
        // 日期补位，因为前端只传到了yyyy-MM-dd HH:mm 需要补全后面的ss
        if (StringUtil.isNotBlank(shopGarrisonDataPageParam.getBeginTime())) {
            shopGarrisonDataPageParam.setBeginTime(shopGarrisonDataPageParam.getBeginTime() + ":00");
        }
        if (StringUtil.isNotBlank(shopGarrisonDataPageParam.getEndTime())) {
            shopGarrisonDataPageParam.setEndTime(shopGarrisonDataPageParam.getEndTime() + ":59");
        }
        Page<ShopGarrisonRecord> page = new PageInfo<>(shopGarrisonDataPageParam);
        IPage<ShopGarrisonDataVo> iPage = shopGarrisonRecordMapper.getShopGarrisonDataList(page, shopGarrisonDataPageParam);
        return new Paging<ShopGarrisonDataVo>(iPage);
    }

}
